var gamejs = require("gamejs");
var Enemy = require("js/enemy").Enemy;
var Match = require("js/match").Match;
var Map = require("js/map").Map;
qModule("js/enemy");

var currentMatch = new Match();
currentMatch.setMap(new Map(currentMatch, MAP_WIDTH, MAP_HEIGHT));
var testEnemy = new Enemy(currentMatch, [50, 50]);

test("test for Enemy(match, position)[constructor]", function() {
	ok(testEnemy instanceof Enemy, "ok for valid coordinates [50, 50]");
	
	//tests findPath
	var startPoint = [650, 200];
	testEnemy = new Enemy(currentMatch, startPoint);
	var path = testEnemy.path;
	deepEqual(path[0], startPoint, "[findPath] ok for start from the given point");
	strictEqual((path[path.length - 1])[X], 0, "[findPath] ok for the reaching of a valid point(0 as abscissa)");
	var tmp = (path[path.length - 1])[Y] - (PLANET_CENTER - PLANET_HEIGHT / 2);
	ok((tmp < PLANET_HEIGHT) && (tmp >= 0), "[findPath] ok for the reaching of a valid point(ordinate in range)");
	
	var isOk = true;
	var oldPoint = startPoint;
	for(i = 0; (i < path.length) && (isOk); i++) {
		var dx = Math.abs(oldPoint[X] - (path[i])[X]);
		var dy = Math.abs(oldPoint[Y] - (path[i])[Y]);
		isOk = ((dx <= 1) && (dy <= 1));
		oldPoint = path[i];
	}
	ok(isOk, "[findPath] ok for steps of a pixel");
	//end findPath tests
	
	var testEnemy2 = new Enemy(currentMatch, [0, 0]);
	deepEqual(testEnemy2.getCenter(), [0, 0], "ok for valid coordinates [0, 0]");
	
	throws(function() {
		testEnemy2 = new Enemy(currentMatch, [-5, 0]);
	}, RangeError, "ok for invalid coordinates [-5, 0][raise a RangeError]");
	
	throws(function() {
		testEnemy2 = new Enemy(currentMatch, [100, MAP_HEIGHT]);
	}, RangeError, "ok for invalid coordinates [100, MAP_HEIGHT][raise a RangeError]");
	
	throws(function() {
		testEnemy2 = new Enemy(undefined, [40, 40]);
	}, TypeError, "ok for match = undefined[raise a TypeError]");
	
	throws(function() {
		testEnemy2 = new Enemy(null, [40, 40]);
	}, TypeError, "ok for match = null[raise a TypeError]");
	
	throws(function() {
		testEnemy2 = new Enemy(currentMatch, [40]);
	}, TypeError, "ok for position not in valid format[raise a TypeError]");
	
	throws(function() {
		testEnemy2 = new Enemy(currentMatch, undefined);
	}, TypeError, "ok for rect = undefined[raise a TypeError]");
});

test("test for getMatch()", function() {
	strictEqual(testEnemy.getMatch(), currentMatch, "ok for the correct object returned");
});

test("test for getBoundingRect()", function() {
	var center = [50, 50];
	testEnemy = new Enemy(currentMatch, center);
	var size = testEnemy.image.getSize();
	var topLeft = [center[X] - Math.round(size[WIDTH] / 2), center[Y] - Math.round(size[HEIGHT] / 2)];
	var expectedRect = new gamejs.Rect(topLeft, size);
	deepEqual(testEnemy.getBoundingRect(), expectedRect, "ok for the correct rect returned");
});

test("test for getCenter()", function() {
	var expectedCenter = [51, 52];
	testEnemy = new Enemy(currentMatch, expectedCenter);
	deepEqual(testEnemy.getCenter(), expectedCenter, "ok for the correct coordinates returned");
});

test("test for hit(hitRate)", function(){
	testEnemy = new Enemy(currentMatch, [50, 50]);
	var tmpLife = testEnemy.hit(0);
	strictEqual(testEnemy.hit(1), tmpLife - 1, "ok for 0 < hitRate < Enemy.health");
	
	testEnemy = new Enemy(currentMatch, [50, 50]);
	tmpLife = testEnemy.hit(0);
	strictEqual(testEnemy.hit(tmpLife), 0, "ok for hitRate = Enemy.health");
	
	testEnemy = new Enemy(currentMatch, [50, 50]);
	tmpLife = testEnemy.hit(0);
	strictEqual(testEnemy.hit(tmpLife + 2), 0, "ok for hitRate > Enemy.health");
	
	testEnemy = new Enemy(currentMatch, [50, 50]);
	throws(function() {
		testEnemy.hit(-5);
	}, RangeError, "ok for hitRate < 0[raise a RangeError]");
	
	var isOk = true;
	for(i = 0; (i < tmpLife + 20) && (isOk); i++) {
		testEnemy = new Enemy(currentMatch, [50, 50]);
		tmpLife = testEnemy.hit(0);
		testEnemy.hit(i);
		if(i >= tmpLife) {
			isOk = testEnemy.isDead();
		}
		else {
			isOk = ! testEnemy.isDead();
		}
	}
	ok(isOk, "ok for killing only when hitRate >= Enemy.healt");
});

test("test for setDetected(detected)", function(){
	//testEnemy.detected is a number, it evaluates to false only if it's 0
	testEnemy.setDetected(true);
	ok(testEnemy.detected, "ok for detected = true");
	
	testEnemy.setDetected(false);
	ok( ! testEnemy.detected, "ok for detected = false");
	
	testEnemy.setDetected();
	ok(testEnemy.detected, "ok for detected not defined[it's detected]");
});

test("test for isDetected()", function(){
	testEnemy.setDetected(true);
	ok(testEnemy.isDetected(),"ok for detected enemy");
	
	testEnemy.setDetected(false);
	ok(!testEnemy.isDetected(),"ok for not detected enemy");
});

//just a little test, we not give an invalid msDuration to it
test("test for update(msDuration)", function(){
	testEnemy.pathIndex = 20;
	testEnemy.update(100);
	var testIndex = 20 + Math.round(testEnemy.speed * (100 / 1000));
	var path = testEnemy.path;
	deepEqual(path[Math.round(testEnemy.pathIndex)], path[testIndex],"ok the movement for msDuration > 0");
});